package com.common.tools.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.common.api.exception.CommonException;
import com.common.tools.api.dto.DictTypeDto;
import com.common.tools.api.service.DictTypeService;
import com.common.tools.dao.DictItemMapper;
import com.common.tools.dao.DictTypeMapper;
import com.common.tools.po.DictItemPo;
import com.common.tools.po.DictTypePo;
import com.common.tools.util.ToolsConstant;
import com.common.util.GenerateSequenceUtil;
import io.jsonwebtoken.lang.Collections;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 字典分类表服务实现类
 * </p>
 *
 * @author system
 */
@Slf4j
@Service
public class DictTypeServiceImpl extends DictTypeService {

    @Autowired
    private DictTypeMapper dictTypeMapper;

    @Autowired
    private DictItemMapper dictItemMapper;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public int dels(List<String> idList) {
        try {
            validateSelectedDictType(idList);
            // 根据id查询字典分类信息
            List<DictTypePo> dictTypePos = validateSelectedDictTypeByDatabase(idList);
            // 校验并且给出错误提示(不允许删除以SYS开头的字典分类信息)
            validateDictTypePos(dictTypePos);
            // 过滤出非系统字典类型
            List<String> dictTypeCodeList = colDictTypeCodeToList(dictTypePos);
            // 先删除字典项信息
            dictItemMapper.delete(Wrappers.lambdaQuery(DictItemPo.class)
                    .in(DictItemPo::getDictTypeCode, dictTypeCodeList));
            // 删除字典分类信息
            dictTypeMapper.deleteBatchIds(idList);
            return 1;
        } catch (Exception e) {
            log.error("删除字典分类失败，原因是：{}，ID列表：{}", e.getMessage(), JSON.toJSONString(idList));
            throw e;
        }
    }

    private List<DictTypePo> validateSelectedDictTypeByDatabase(List<String> idList) {
        List<DictTypePo> dictTypePoList = dictTypeMapper.selectBatchIds(idList);
        if (Collections.isEmpty(dictTypePoList)) {
            throw new CommonException("未查询到要删除的字典分类信息！");
        }
        return dictTypePoList;
    }

    private void validateSelectedDictType(List<String> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            throw new CommonException("请选择要删除的字典分类！");
        }
    }

    private void validateDictTypePos(List<DictTypePo> dictTypePos) throws CommonException {
        dictTypePos.stream()
                .filter(dictTypePo -> isSysDictType(dictTypePo.getDictTypeCode()))
                .findAny()
                .ifPresent(dictTypePo -> {
                    String errorMsg = "不允许删除以" + ToolsConstant.SYS_DICT + "开头的字典分类！";
                    log.error(errorMsg);
                    throw new CommonException(errorMsg);
                });
    }

    private List<String> colDictTypeCodeToList(List<DictTypePo> dictTypePos) {
        return dictTypePos.stream()
                .map(DictTypePo::getDictTypeCode)
                .collect(Collectors.toList());
    }

    // 判断是否为系统字典分类
    private boolean isSysDictType(String dictTypeCode) {
        return StringUtils.isNotBlank(dictTypeCode) && dictTypeCode.startsWith(ToolsConstant.SYS_DICT);
    }



    @Transactional(rollbackFor = Exception.class)
    @Override
    public int add(DictTypeDto dto) {
        try {
            validateAndAddDictType(dto);
            // 新增字典信息
            dictTypeMapper.insert(dto);
            return 1;
        } catch (Exception e) {
            log.info("新增字典分类失败，{}", e.getMessage());
            throw e;
        }
    }


    private void validateAndAddDictType(DictTypeDto dto) {
        validateDictTypeDto(dto);
        validateSysDictType(dto.getDictTypeCode());
        checkDictTypeCodeUnique(dto.getDictTypeCode());
        // 新增字典的时候，生成字典的ID
        prepareDictTypeDto(dto);
    }

    private void prepareDictTypeDto(DictTypeDto dto) {
        if (StringUtils.isBlank(dto.getId())) {
            dto.setId(GenerateSequenceUtil.generateSequenceNo());
            dto.setCreateTime(new Date());
            dto.setUpdateTime(new Date());
        } else {
            dto.setUpdateTime(new Date());
        }
    }

    private void checkDictTypeCodeUnique(String dictTypeCode) {
        boolean exists = dictTypeMapper.exists(Wrappers.lambdaQuery(DictTypePo.class)
                .eq(DictTypePo::getDictTypeCode, dictTypeCode));
        if (exists) {
            throw new CommonException("字典分类编码不允许重复！");
        }
    }

    private void validateSysDictType(String dictTypeCode) {
        if (dictTypeCode.startsWith(ToolsConstant.SYS_DICT)) {
            throw new CommonException("不允许设置字典分类编码(以SYS开头的编码)！");
        }
    }

    private void validateDictTypeDto(DictTypeDto dto) {
        if (Objects.isNull(dto)) {
            throw new CommonException("字典类型信息不能为空！");
        }
        validateField(dto.getDictTypeCode(), "字典分类编码");
        validateField(dto.getDictTypeName(), "字典分类名称");
    }

    private void validateField(String value, String filedName) {
        if (StringUtils.isBlank(value)) {
            throw new CommonException(filedName + "不能为空！");
        }
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public int modify(DictTypeDto dto) {
        try {
            validateAndUpdateDictType(dto);
            dictTypeMapper.updateById(dto);
            return 1;
        } catch (Exception e) {
            log.info("修改字典分类失败，{}", e.getMessage());
            throw e;
        }

    }

    private void validateAndUpdateDictType(DictTypeDto dto) {
        validateDictTypeDto(dto);
        validateSysDictType(dto.getDictTypeCode());
        DictTypePo dictTypePo = checkDictTypeExist(dto.getId());
        checkDictTypeCodeModification(dto, dictTypePo);
        // 修改字典信息
        prepareDictTypeDto(dto);
    }

    private void checkDictTypeCodeModification(DictTypeDto dictTypeDto, DictTypePo dictTypePo) {
        checkFieldModification(dictTypePo.getDictTypeCode(), dictTypeDto.getDictTypeCode(), "字典分类编码");
    }

    private void checkFieldModification(String oldValue, String newValue, String errorMessage) {
        // 方法入参判空已经在上一步做过了
        if (!Objects.equals(oldValue, newValue)) {
            throw new CommonException(errorMessage + "不允许修改！");
        }
    }

    private DictTypePo checkDictTypeExist(String dictTypeId) {
        return Optional.ofNullable(dictTypeMapper.selectById(dictTypeId))
                .orElseThrow(() -> new CommonException("未查到当前要修改的字典分类！！"));
    }


    @Override
    public List<String> getSearchKeyList() {
        return Arrays.asList("dict_type_code", "dict_type_name");
    }

}
